<script lang="tsx">
import type { CSSProperties, PropType, VNode } from 'vue';
import type { DescriptionsProps } from 'ant-design-vue';
import type { DescItem, DescInstance, DescriptionProps } from './typing';

import { get, isFunction } from '@vben/utils';
import { useDesign } from './useDesign';
import { Descriptions } from 'ant-design-vue';
import { computed, defineComponent, ref, toRefs, unref, useAttrs } from 'vue';

// 定义组件的 props
const componentProps = {
  title: { type: String, default: '' },
  // 新增 showTitle 属性
  showTitle: { type: Boolean, default: true },
  // 新增 showColon 属性
  showColon: { type: Boolean, default: true },
  size: {
    type: String,
    validator: (v: string) => ['small', 'default', 'middle', undefined].includes(v),
    default: 'default',
  },
  bordered: { type: Boolean, default: true },
  column: {
    type: [Number, Object],
    default: () => {
      return { xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 };
    },
  },
  schema: {
    type: Array as PropType<DescItem[]>,
    default: () => [],
  },
  data: { type: Object },
};

export default defineComponent({
  name: 'Description',
  props: componentProps,
  emits: ['register'],
  setup(props, { slots, emit }) {
    // 定义响应式变量
    const propsRef = ref<Partial<DescriptionProps> | null>(null);
    const { prefixCls } = useDesign('description');
    const attrs = useAttrs();

    // 计算合并后的 props
    const getMergeProps = computed(() => {
      return {
        ...props,
        ...(unref(propsRef) as any),
      } as DescriptionProps;
    });

    // 计算去除 title 的 props
    const getProps = computed(() => {
      const opt = {
        ...unref(getMergeProps),
        title: undefined,
      };
      return opt as DescriptionProps;
    });

    const getDescriptionsProps = computed(() => {
      // 根据 showTitle 决定是否包含 title
      const { title, showTitle, ...restProps } = unref(getMergeProps);
      const descriptionsProps = {
        ...unref(attrs),
        ...restProps,
      } as DescriptionsProps;

      if (showTitle) {
        descriptionsProps.title = title;
      }

      return descriptionsProps;
    });

    // 设置描述信息的 props
    function setDescProps(descProps: Partial<DescriptionProps>): void {
      propsRef.value = {
        ...(unref(propsRef) as Record<string, any>),
        ...descProps,
      } as Record<string, any>;
    }

    // 渲染标签 - 添加冒号控制
    function renderLabel({ label, labelMinWidth, labelStyle }: DescItem) {
      // 根据 showColon 属性决定是否添加冒号
      const labelContent = unref(getMergeProps).showColon ? `${label}:` : label;

      if (!labelStyle && !labelMinWidth) {
        return labelContent;
      }

      const labelStyles: CSSProperties = {
        ...labelStyle,
        minWidth: `${labelMinWidth}px `,
      };
      return <div style={labelStyles}>{labelContent}</div>;
    }

    // 渲染每个展示项
    function renderItem() {
      const { schema, data } = unref(getProps);
      return unref(schema)
        .map((item) => {
          const { render, fieldName: field, span, show, contentMinWidth } = item;

          if (show && isFunction(show) && !show(data)) {
            return null;
          }

          const getContent = () => {
            const _data = unref(getProps)?.data;
            if (!_data) {
              return null;
            }
            const getField = get(_data, field);
            // eslint-disable-next-line
            if (getField && !toRefs(_data).hasOwnProperty(field)) {
              return isFunction(render) ? render('', _data) : '';
            }
            return isFunction(render) ? render(getField, _data) : getField ?? '';
          };

          const width = contentMinWidth;
          return (
            <Descriptions.Item key={field} label={renderLabel(item)} span={span}>
              {() => {
                if (!contentMinWidth) {
                  return getContent();
                }
                const style: CSSProperties = {
                  minWidth: `${width}px`,
                };
                return <div style={style}>{getContent()}</div>;
              }}
            </Descriptions.Item>
          );
        })
        .filter((item) => !!item);
    }

    // 渲染插槽内容
    function renderSlots() {
      const slotNodes: VNode[] = [];

      // 1. 渲染所有具名插槽（除了 default）
      Object.keys(slots).forEach((name) => {
        if (name !== 'default') {
          const slotContent = slots[name]?.({
            data: unref(getProps)?.data, // 传递数据给插槽，插槽中可以通过 `props.data` 访问?v-slot="{data}"获取??
          });
          if (slotContent) {
            slotNodes.push(...slotContent);
          }
        }
      });

      // 2. 渲染默认插槽
      if (slots.default) {
        const defaultSlot = slots.default({
          data: unref(getProps)?.data, // 传递数据给插槽
        });
        if (defaultSlot) {
          slotNodes.push(...defaultSlot);
        }
      }

      return slotNodes;
    }
    // 渲染 Descriptions 组件
    const renderDesc = () => {
      return (
        <Descriptions class={`${prefixCls}`} {...(unref(getDescriptionsProps) as any)}>
          {renderItem()}
          {renderSlots()}
        </Descriptions>
      );
    };

    const methods: DescInstance = {
      setDescProps,
    };

    emit('register', methods);
    return () => renderDesc();
  },
});
</script>
